package com.DJRelayAndroidClient_ACE.djrelay_androidclient;

import java.lang.ref.WeakReference;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.widget.CompoundButton.OnCheckedChangeListener;

import com.DJRelayAndroidClient_ACE.djrelay_androidclient.MainActivity.requestType;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.plus.PlusClient;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerView;
import com.google.android.youtube.player.YouTubePlayer.ErrorReason;
import com.google.android.youtube.player.YouTubePlayer.PlayerStateChangeListener;
import com.google.android.youtube.player.YouTubePlayer.Provider;

public class LoginActivity extends Activity implements  OnClickListener,
PlusClient.ConnectionCallbacks, PlusClient.OnConnectionFailedListener {

	private static final int DIALOG_GET_GOOGLE_PLAY_SERVICES = 1;

	private static final int REQUEST_CODE_SIGN_IN = 1;
	private static final int REQUEST_CODE_GET_GOOGLE_PLAY_SERVICES = 2;

	public static Handler mHandler;
	public static ServerHandler mServerHandler;
	private static HttpHelper mLoginHttpHelper;
	
	public PlusClient mPlusClient;
	public ConnectionResult mConnectionResult;

	private Button submitButton, signOutButton;
	private RadioGroup radioSessionGroup;
	private RadioButton radioSessionButton;
	private SignInButton plusButton;
	private TextView mSignInStatus;
	private EditText mSessionID;
	private String mPersonName, mPersonId, sessionID;
	
	private static ImageView dasDJ;
	private ProgressDialog mProgressDialog;
	
	private boolean signOutFlag = false;
	public static boolean createSession = false;

	@Override 
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login_view);  
		
		dasDJ = (ImageView) findViewById(R.id.djView);
		dasDJ.setImageResource(R.drawable.das_dj);

		submitButton = (Button) findViewById(R.id.loginSubmit_button);
		submitButton.setOnClickListener(this);

		plusButton = (SignInButton) findViewById(R.id.gPlusSignIn_button);
		plusButton.setOnClickListener(this);

		signOutButton = (Button) findViewById(R.id.gPlusSignOut_button);
		signOutButton.setOnClickListener(this);
		
	    mSessionID = (EditText) findViewById(R.id.sessionID_editText);
		
		mSignInStatus = (TextView) findViewById(R.id.gPlusStatus_textView);

		mPlusClient = new PlusClient.Builder(this, this, this).build();  
		
		signOutFlag = true;
		
		mLoginHttpHelper = new HttpHelper(MainActivity.LOGIN_ACTIVITY);
		
		mServerHandler = new ServerHandler(this);
	}
	
	static class ServerHandler extends Handler {
		private final WeakReference<LoginActivity> mLoginActivity;
		
		ServerHandler(LoginActivity loginActivity) {
			mLoginActivity = new WeakReference<LoginActivity>(loginActivity);
		}

    	@Override
    	public void handleMessage(Message msg){
    		LoginActivity loginActivity = mLoginActivity.get();
    		if (loginActivity != null) {
    			loginActivity.handleMessage(msg);
    		}
    	}
	}
	
	public void handleMessage(Message msg){
		/* *** Return codes: ***
	 	0 = HTTP error
	 	1 = JSON error
	 	2 = CREATE_TABLE success
	 	3 = JOIN_TABLE success
	 	4 = UPDATE_SONG success
	 	5 = UPDATE_FEED success
		6 = FETCH_FEED success
	 	7 = USER_LOG_OUT success
	 	8 = KILL_SESSION success
	 ************************** */
		Log.d("myApp", "Login Activity Static Message Handler invoked");
		if(msg.what == 2 || msg.what == 3){
			try {
				mProgressDialog.dismiss();
				
				// Collect Status bits from Server query and check for any errors
				if (createSession)
					MainActivity.readServerResponse(requestType.CREATE_SESSION, mLoginHttpHelper);
				else
					MainActivity.readServerResponse(requestType.JOIN_SESSION, mLoginHttpHelper);
				
				if (MainActivity.dbCon == "true" && ((MainActivity.createTable == "true" && 
						MainActivity.insertMaster == "true") || (MainActivity.insertUser == "true"))) {
					Log.i("myApp", "Login Success, dbCon = " + MainActivity.dbCon + ", createTable = "
						+ MainActivity.createTable + ", insertMaster = " + MainActivity.insertMaster + ", "
						+ "insertUser = " + MainActivity.insertUser);
					Bundle extras = new Bundle();
					extras.putString("NAME", mPersonName);
					extras.putString("ID", mPersonId);
					extras.putString("SESSION_ID", mSessionID.getText().toString());
					getIntent().putExtras(extras);
					setResult(RESULT_OK, getIntent());
					finish();
				} else {
					Log.w("myApp", "Login Failure, dbCon = " + MainActivity.dbCon + ", createTable = "
    						+ MainActivity.createTable + ", insertMaster = " + MainActivity.insertMaster + ", "
    						+ "insertUser = " + MainActivity.insertMaster);
					// TODO - notify user, specify details of database connection issue
					// e.g. existing user, master, etc..
					popServerError();
				}
			} catch (NullPointerException npe) {
				Log.w("myApp", "Either HTTP class or Tube Player Not instantiated!!" + npe.toString());
			}
		}
		else if (msg.what == 0) {	// This still takes too long to realize server connection is down..
			mProgressDialog.dismiss();
			// TODO - setResult to fail??
			popServerError();
		}
		else {
			mProgressDialog.dismiss();
			Log.w("myApp", "Login Activity Handler message not received properly, JSON error in Login HTTP Helper");
			// TODO - setResult to fail??
			popServerError();
		}
	}

	@Override
	public void onClick(View view) {
		switch(view.getId()) {
		case R.id.gPlusSignIn_button:
			int available = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
			if (available != ConnectionResult.SUCCESS) {
				showDialog(DIALOG_GET_GOOGLE_PLAY_SERVICES);	// TODO - fix me w/ fragment manager
				return;
			}
			signOutFlag = false;
			try {
				mSignInStatus.setText(R.string.signing_in_status);
				mConnectionResult.startResolutionForResult(this, REQUEST_CODE_SIGN_IN);
			} catch (IntentSender.SendIntentException e) {
				// Fetch a new result to start.
				mPlusClient.connect();
			}
			break;
			
		case R.id.gPlusSignOut_button:
			if (mPlusClient.isConnected()) {
				Log.i("myApp", "Sign Out Handler Invoked");
				mPlusClient.clearDefaultAccount();
				mPlusClient.disconnect();
				mPlusClient.connect();
				try {
					mPersonName = mPersonId = null;
				} catch (Exception e) {
					// No need to do anything really here..
				}
			}
			break;
			
		case R.id.loginSubmit_button:
			sessionID = mSessionID.getText().toString();
			if (mPersonName ==  null || 
					mPersonName == getString(R.string.unknown_person)) {
				Context context = getApplicationContext();
				CharSequence text = "You Need to Login to Play!";
				int duration = Toast.LENGTH_SHORT;

				Toast toast = Toast.makeText(context, text, duration);
				toast.setGravity(Gravity.CENTER | Gravity.CENTER, 0, 0);
				toast.show();
			} else if (sessionID == null || sessionID.length() < 6) {
				Context context = getApplicationContext();
				CharSequence text = "Please Enter a Session ID that is at least 6 characters long!";
				int duration = Toast.LENGTH_SHORT;

				Toast toast = Toast.makeText(context, text, duration);
				toast.setGravity(Gravity.CENTER | Gravity.CENTER, 0, 0);
				toast.show();
			} else {
				Bundle extras = new Bundle();
				// Create the Progress Dialog
				mProgressDialog = new ProgressDialog(this);
				mProgressDialog.setTitle("Processing..");
				mProgressDialog.setMessage("Please Wait");
				mProgressDialog.setCancelable(false);
				mProgressDialog.setIndeterminate(true);
				mProgressDialog.show();
				
				if (createSession) {
					try {
						mLoginHttpHelper.httpPostGet(requestType.CREATE_SESSION, MainActivity.serverAddress, 
								MainActivity.songCueAddress,
								"createSession", "true",
								"sessionID", sessionID,
								"userID", mPersonId,
								"user", mPersonName);
					} catch (Exception e) {
						Log.i("myApp", "Unable to connect to server in Login Activity: " + e.getMessage());
						// TODO notify user
					} 
				} else {
					try {
						mLoginHttpHelper.httpPostGet(requestType.JOIN_SESSION, MainActivity.serverAddress, 
								MainActivity.songCueAddress,
								"joinSession", "true",
								"sessionID", sessionID,
								"userID", mPersonId,
								"user", mPersonName);
					} catch (Exception e) {
						Log.i("myApp", "Unable to connect to server in Login Activity: " + e.getMessage());
						// TODO notify user
					} 
				}
			}
			break;
			
		case R.id.createSession_radioButton:
		case R.id.joinSession_radioButton:
			Log.d("myApp", "radioSession onClick handler invoked");
			// fetch selected radio button from the group and update flag
			radioSessionGroup = (RadioGroup) findViewById(R.id.radioSession);
			int selectedID = radioSessionGroup.getCheckedRadioButtonId();
			radioSessionButton = (RadioButton) findViewById(selectedID);
			if (radioSessionButton == findViewById(R.id.joinSession_radioButton))
				createSession = false;
			else
				createSession = true;
			Log.i("myApp", "Radio Button = " +  radioSessionButton.getText() + " and createSession = " + createSession);
			break;
		}           
	}	
	
	private void popServerError() {
		Context context = getApplicationContext();
		CharSequence text = "DJ Relay servers are down. Try again later..";
		int duration = Toast.LENGTH_SHORT;

		Toast toast = Toast.makeText(context, text, duration);
		toast.setGravity(Gravity.CENTER | Gravity.CENTER, 0, 0);
		toast.show();
	}

	@Override
	protected Dialog onCreateDialog(int id) {		// TODO - update with a DialogFragment
		if (id != DIALOG_GET_GOOGLE_PLAY_SERVICES) {
			return super.onCreateDialog(id);
		}

		int available = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		if (available == ConnectionResult.SUCCESS) {
			return null;
		}
		if (GooglePlayServicesUtil.isUserRecoverableError(available)) {
			return GooglePlayServicesUtil.getErrorDialog(
					available, this, REQUEST_CODE_GET_GOOGLE_PLAY_SERVICES);
		}
		return new AlertDialog.Builder(this)
		.setMessage(R.string.plus_generic_error)
		.setCancelable(true)
		.create();
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == REQUEST_CODE_SIGN_IN
				|| requestCode == REQUEST_CODE_GET_GOOGLE_PLAY_SERVICES) {
			if (resultCode == RESULT_OK && !mPlusClient.isConnected()
					&& !mPlusClient.isConnecting()) {
				// This time, connect should succeed.
				mPlusClient.connect();
			}
		}
	}

	@Override
	public void onConnected(Bundle connectionHint) {
		
		if (mPlusClient.getCurrentPerson() != null) {
			mPersonName = mPlusClient.getCurrentPerson().getDisplayName();
			mPersonId = mPlusClient.getCurrentPerson().getId();
		} else
			mPersonName = getString(R.string.unknown_person);

		mSignInStatus.setText(getString(R.string.signed_in_status, mPersonName));
		updateButtons(true /* isSignedIn */);

		if (signOutFlag){
			Bundle b = getIntent().getExtras();
			if (b != null) {
				if (b.getInt("SignOut") == 1) {
					Log.i("myApp", "Received extras from main in Login");
					signOutButton.performClick();	
					signOutFlag = false;
				}
			}
		}
	}


	@Override
	public void onDisconnected() {
		mSignInStatus.setText(R.string.loading_status);
		mPlusClient.connect();
		updateButtons(false /* isSignedIn */);
	}  

	@Override
	public void onConnectionFailed(ConnectionResult result) {
		mConnectionResult = result;
		updateButtons(false /* isSignedIn */);
	}

	private void updateButtons(boolean isSignedIn) {
		if (isSignedIn) {
			plusButton.setVisibility(View.INVISIBLE);
			signOutButton.setEnabled(true);
		} else {
			if (mConnectionResult == null) {
				// Disable the sign-in button until onConnectionFailed is called with result.
				plusButton.setVisibility(View.INVISIBLE);
				mSignInStatus.setText(getString(R.string.loading_status));
			} else {
				// Enable the sign-in button since a connection result is available.
				plusButton.setVisibility(View.VISIBLE);
				mSignInStatus.setText(getString(R.string.signed_out_status));
			}

			signOutButton.setEnabled(false);
		}
	}

	@Override
	public void onStart() {
		super.onStart();
		mPlusClient.connect();
	}

	@Override
	public synchronized void onResume() {
		super.onResume();
	}

	@Override
	public synchronized void onPause() {
		super.onPause();
	}

	@Override
	public void onStop() {
		mPlusClient.disconnect();
		super.onStop();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}
}
